/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Controller;

import Model.Celdam;
import Model.twoWays;
import View.PPL;
import View.PanelEntrada;
import View.PanelProblema;
import View.VentanaIngresoTaos;
import View.VentanaPrincipal;
import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 *
 * @author Martin Kanayet
 */
public final class MainController {

    public static VentanaPrincipal ventanaPrincipal;
    public static double lambda1;
    public static double lambda2;
    public static double lambda3;
    public static double lambda4;
    public static double lambda1Est;
    public static double lambda2Est;
    public static double lambda3Est;
    public static double lambda4Est;
    
    public static double puntoCritico = 0;

    public static void generarLambdas(ArrayList<Double> Ks) {
        double varianza = 0;
        double granMedia = twoWays.getGranMedia();
        for (int i = 0; i < Ks.size(); i++) {
            varianza = varianza + Math.pow((Ks.get(i) - granMedia), 2);
        }
        varianza = varianza / Ks.size();
        twoWays.setVarianza(varianza);

        double mEst = varianza / ((Math.pow(twoWays.getError(), 2)) * twoWays.getSignificancia());
        int mEstimado = 1 + (int) mEst; //Garantizar que sea mayor con machetazo
        twoWays.setmEstimado(mEstimado);

        ArrayList<Double> Km = crearMasKs();
        double muestra[];            // declarar la referencia a un arreglo
        muestra = new double[Km.size()];

        //Copiar a arreglo para pasar al programa de obtencion de lambdas
        for (int i = 0; i < Km.size(); i++) {
            muestra[i] = Km.get(i);
        }
//        EstandarxDLG Edlg = new EstandarxDLG();
//        ModuloDLG Mdlg = new ModuloDLG(Edlg);     
//        Mdlg.evaluar(muestra, 1, Edlg.getErrMax(), Edlg.getPobla(), Edlg.getGenerac(), Edlg.getProbmuta(), Edlg.getProbcruce());
//        ParametrosSalida salida = new ParametrosSalida();
//        salida=(ParametrosSalida)Edlg.obtenerResultados(); 
//        System.out.println("Lambda1:" + salida.lambda1 + " Lambda2: "+ salida.lambda2 + " Lambda3: "+ salida.lambda3+ " Lambda4:"+ salida.lambda4);


        ParametrosEntrada entrada = new ParametrosEntrada();
        entrada.muestra = muestra;
        entrada.ProbCruce = 0.5;
        entrada.ProbMutacion = 0.025;
        entrada.poblacion = 100;
        entrada.generaciones = 10000;
        entrada.ErrorEsperado = 1.0E-15;
        entrada.metodo = 1; // met percentiles

        JFrame frame = new JFrame("Estimación de parámetros DLG mediante AG");
        EstandarxDLG dlg2 = new EstandarxDLG(-0.2499, 2);//con espacio de bsuqeda definido
        dlg2.ponerParametros(entrada, 0);
        frame.getContentPane().add(dlg2,BorderLayout.CENTER);
        frame.add(dlg2); // se pone en el jframe
        //frame.setVisible(true);
        //frame.setSize(615, 460);
        dlg2.ejecutar();

        System.out.println("lambda 1: " + lambda1Est);
        System.out.println("lambda 2: " + lambda2Est);
        System.out.println("lambda 3: " + lambda3Est);
        System.out.println("lambda 4: " + lambda4Est);
        
        dlg.la1 = lambda1Est;
        dlg.la2 = lambda2Est;
        dlg.la3 = lambda3Est;
        dlg.la4 = lambda4Est;
        System.out.println(dlg.sonLambdasValidos());
        double vc = calcularValorCritico(twoWays.getAlpha());
        System.out.println(vc);
        puntoCritico = vc;
/*        System.out.println("Más pruebas");
        ModuloDLG dlg3 = new ModuloDLG();
        
        double[] x={1,2,3,4,5,6};
        dlg3.evaluar(x,1, 1.0E-15, 200,20000, 0.6,0.03);
        
        System.out.println("lambda 1: " + lambda1Est);
        System.out.println("lambda 2: " + lambda2Est);
        System.out.println("lambda 3: " + lambda3Est);
        System.out.println("lambda 4: " + lambda4Est);
     
        double vcrr = calcularValorCritico(twoWays.getAlpha());
        System.out.println(vcrr);     */
    }

    public static ArrayList<Double> crearMasKs() {
        ArrayList<Double> nuevos = new ArrayList<Double>();
        for (int x = 0; x < twoWays.getmEstimado(); x++) {
            MatrizDatos matriz = new MatrizDatos();
            matriz.ordenamientoSecuencia();
            System.out.println("Varianza: " + twoWays.getVarianza() + " Error: " + twoWays.getError() + " Significancia: " + twoWays.getSignificancia() + " M estimado: " + twoWays.getmEstimado());
            int filas = twoWays.getMatriz().length;
            int columnas = twoWays.getMatriz()[0].length;
            for (int i = 0; i < filas; i++) {
                for (int j = 0; j < columnas; j++) {
                    System.out.println("Número de datos: " + twoWays.getMatriz()[i][j].getDatos() + " Fila: " + i + " Columna: " + j + " lambda1: " + twoWays.getMatriz()[i][j].getLambda1() + " lambda2: " + twoWays.getMatriz()[i][j].getLambda2() + " lambda3: " + twoWays.getMatriz()[i][j].getLambda3() + " lambda4: " + twoWays.getMatriz()[i][j].getLambda4());
                    for (int k = 0; k < twoWays.getMatriz()[i][j].getDatos(); k++) {
                        System.out.println(twoWays.getMatriz()[i][j].getValores().get(k));
                    }
                    System.out.println("-----------------------");
                }
            }
            double KGeneralizada = 0;
            //MainController.simular();
            Calculadora c = new Calculadora();
            KGeneralizada = c.Kgeneralizada();
            nuevos.add(KGeneralizada);
            System.out.println("La K Generalizada linda es: " + KGeneralizada);
            System.out.println("La K askldjaskldjasd: " + c.estadisticaFriedman(5, filas, columnas));
            KGeneralizada = 0;
            MainController.reRegenerarDatos();
        }

        return nuevos;
    }

    public MainController() {
        setupMC();
    }

    public static void reRegenerarDatos() {
        double valor = 0;
        for (int i = 0; i < twoWays.getI(); i++) {
            for (int j = 0; j < twoWays.getJ(); j++) {
                ArrayList<Double> nuevo = new ArrayList<Double>();
                for (int k = 0; k < twoWays.getMatriz()[i][j].getDatos(); k++) {
                    Calculadora calc = new Calculadora();
                    while (nuevo.indexOf(valor) != -1) {
                        valor = calc.generarDatos(twoWays.getGranMedia(), twoWays.getBeta(), i, j, twoWays.getMatriz()[i][j].getLambda1(), twoWays.getMatriz()[i][j].getLambda2(), twoWays.getMatriz()[i][j].getLambda3(), twoWays.getMatriz()[i][j].getLambda4());
                    }

                    nuevo.add(valor);
                }
                twoWays.getMatriz()[i][j].setValores(nuevo);
            }
        }

    }

    public static boolean validarTaosYBetas(String taos, String betas) {
        Character aux = null;
        if (taos.isEmpty() || betas.isEmpty()) {
            return false;
        }
        for (int i = 0; i < taos.length(); i++) {
            if (!aux.isDigit(taos.charAt(i)) && taos.charAt(i) != ',' && taos.charAt(i) != '.') {
                return false;
            }
        }

        for (int i = 0; i < betas.length(); i++) {
            if (!aux.isDigit(betas.charAt(i)) && betas.charAt(i) != ',' && betas.charAt(i) != '.') {
                return false;
            }
        }

        if (!almacenarTaosYBetas(taos, betas)) {
            return false;
        }

        return true;
    }

    public void setupMC() {
        ventanaPrincipal = new VentanaPrincipal();
        PanelEntrada panelEntrada = new PanelEntrada();
        setPanel(panelEntrada);
        ventanaPrincipal.setVisible(true);
    }
    public static DLG dlg = new DLG();
    
/*    public static void simular() {



        
        lambda1 = dlg.la1;
        lambda2 = dlg.la2;
        lambda3 = dlg.la3;
        lambda4 = dlg.la4;

        System.out.println(dlg.sonLambdasValidos());
        System.out.println(twoWays.getAlpha() + " " + lambda1 + " " + lambda2 + " " + lambda3 + " " + lambda4);
        double valorCritico = calcularValorCritico(twoWays.getAlpha());
        puntoCritico = valorCritico;
        System.out.println(valorCritico);

    }*/

    public static double calcularValorCritico(double alpha) {
        double resultado = 0;
        resultado = lambda1Est + (((Math.pow((1 - alpha), lambda3Est)) - (Math.pow(alpha, lambda4Est))) / lambda2Est);
        return resultado;
    }

    private static boolean almacenarTaosYBetas(String taos, String betas) {
        String[] listaTaos;
        String[] listaBetas;
        int puntos = 0;
        listaTaos = taos.split(",");
        listaBetas = betas.split(",");

        if (twoWays.getI() != listaBetas.length) {
            return false;
        }

        if (twoWays.getJ() != listaTaos.length) {
            return false;
        }

        for (int i = 0; i < listaTaos.length; i++) {
            for (int j = 0; j < listaTaos[i].length(); j++) {
                if (listaTaos[i].charAt(j) == '.') {
                    puntos++;
                }
            }
            if (puntos > 1) {
                return false;
            }
            puntos = 0;
        }

        for (int i = 0; i < listaBetas.length; i++) {
            for (int j = 0; j < listaBetas[i].length(); j++) {
                if (listaBetas[i].charAt(j) == '.') {
                    puntos++;
                }
            }
            if (puntos > 1) {
                return false;
            }
            puntos = 0;
        }
        for (int i = 0; i < listaTaos.length; i++) {
            twoWays.getListaTaos().add(Double.parseDouble(listaTaos[i]));
            System.out.println(listaTaos[i]);
        }
        for (int i = 0; i < listaBetas.length; i++) {
            twoWays.getListaBetas().add(Double.parseDouble(listaBetas[i]));
            System.out.println(listaBetas[i]);
        }

        return true;


    }

    public static void setPanel(JPanel panel) {
        ventanaPrincipal.jPanel1.setVisible(false);
        ventanaPrincipal.jPanel1.removeAll();
        ventanaPrincipal.jPanel1.add(panel);
        ventanaPrincipal.jPanel1.repaint();
        ventanaPrincipal.jPanel1.setVisible(true);
    }

    public static void crearNuevaMatriz(int bloques, int tratamientos, double granMedia, double alpha, double beta, double error, double significancia, double tao, double deltaTao, String datos, int mP, int pP, int rMax) {

        twoWays tw = new twoWays(bloques, tratamientos);
        twoWays.setAlpha(alpha);
        twoWays.setBeta(beta);
        twoWays.setDeltaTao(deltaTao);
        twoWays.setError(error);
        twoWays.setGranMedia(granMedia);
        twoWays.setSignificancia(significancia);
        twoWays.setTao(tao);
        twoWays.setmPiloto(mP);
        twoWays.setpPiloto(pP);
        twoWays.setRegistrosMax(rMax);
        if (datos.equals("Manual")) {
            PanelProblema pp = new PanelProblema(bloques, tratamientos, datos);
            setPanel(pp);
        } else {
            //Se supone que esto me retorna un objeto tipo two ways;
            //tw = generarMatrizAleatoria(bloques, tratamientos);
        }
    }

    public static void calcularVarianza(double granMedia) {
        int contador = 0;
        double varianza = 0;
        Celdam matriz[][] = twoWays.getMatriz();
        for (int i = 0; i < matriz.length; i++) {
            for (int j = 0; j < matriz[0].length; j++) {
                for (int k = 0; k < matriz[i][j].getDatos(); k++) {
                    contador = contador + 1;
                    varianza = varianza + Math.pow((matriz[i][j].getValores().get(k) - granMedia), 2);
                }
            }
        }
        varianza = varianza / contador;
        twoWays.setVarianza(varianza);
    }

    public static void calcularMEstimado(double varianza, double error, double significancia) {
        twoWays.setmEstimado((int) ((varianza) / ((Math.pow(error, 2)) * significancia)));
    }

    public static ArrayList[][][] generarMatrizAleatoria(int bloques, int tratamientos) {
        // generacion de la matriz aleatoria automaticamente
        ArrayList matriz[][][];// matriz general
        int datos = 0;//tamaño de arreglo
        double numero = 0; // numero aleatorio para llenar el arreglo
        int rangoNumero = 99999;//rango del numero aleatorio
        int rangoArreglos = 99;//rango del tamaño de los arreglos
        matriz = new ArrayList[bloques][tratamientos][3];//
        Random ran = new Random();//generador numeros aleatorios

        for (int i = 0; i < bloques; i++) {
            for (int j = 0; j < tratamientos; j++) {
                ArrayList a = new ArrayList();
                datos = ran.nextInt(rangoArreglos);
                for (int k = 0; k < datos; k++) {
                    numero = ran.nextDouble();
                    numero *= rangoNumero;
                    a.add(numero);
                }
                // ingresa a la matriz los datos generados aleatoriamente
                matriz[i][j][0] = a;
                Collections.sort(a);
                //ingresa a la matriz los datos ordenados
                matriz[i][j][1] = a;
            }
        }
        return matriz;
    }

    public static void inicioValoresPorDefecto() {

        int filas = twoWays.getI();
        int columnas = twoWays.getJ();
        Random ran = new Random();
        double aux = 0;
        for (int i = 0; i < filas; i++) {
            aux = ran.nextInt(100);
            twoWays.getListaBetas().add(aux);
            System.out.println("Beta aleatorio: " + aux);
        }
        for (int i = 0; i < columnas; i++) {
            aux = ran.nextInt(100);
            twoWays.getListaTaos().add(aux);
            System.out.println("Tao aleatorio: " + aux);
        }


    }
    public Calculadora calculadora = new Calculadora();
}
